package com.coship.vas.dapg.dao.common;

import java.io.Serializable;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.util.Assert;


/**
 * 
 * 
 * File Name : BaseDaoImpl.java
 * 
 * @Description : 基础DAO，集成hibernate模板，包含通用数据操作方法
 * @author 904304
 */
public abstract class BaseDaoImpl<T> implements BaseDao<T>
{

	@Autowired
	private SessionFactory sessionFactory;

	@Autowired
	private HibernateTemplate hibernateTemplate;

	public void setSessionFactory(SessionFactory sessionFactory)
	{
		this.sessionFactory = sessionFactory;
	}

	public SessionFactory getSessionFactory()
	{
		return sessionFactory;
	}

	public HibernateTemplate getHibernateTemplate()
	{
		return hibernateTemplate;
	}

	public void setHibernateTemplate(HibernateTemplate hibernateTemplate)
	{
		this.hibernateTemplate = hibernateTemplate;
	}

	public Session getSession()
	{
		return sessionFactory.getCurrentSession();
		
	}

	/**
	 * 返回要进行操作的实体类
	 * 
	 * @return
	 * @author zhangyimin
	 * @create 2008-4-22 下午02:35:01
	 */
	public abstract Class<T> getEntryClass();

	/**
	 * 保存一个对象
	 * 
	 * @param obj
	 */
	public void save(T obj)
	{
		this.getHibernateTemplate().save(obj);
	}

	/**
	 * 保存或更新一个对象
	 * 
	 * @param obj
	 */
	public void saveorUpdate(T obj)
	{
		this.getHibernateTemplate().saveOrUpdate(obj);
		
	}

	/**
	 * 执行一条语句
	 * 
	 * @param hql
	 */
	public void execute(String hql)
	{
		Session session = getSession();
		try
		{
			Query query = session.createQuery(hql);
			query.executeUpdate();
		} catch (Exception e)
		{
			e.printStackTrace();
		} finally
		{
			session.disconnect();
		}
	}

	/**
	 * 更新一个对象
	 * 
	 * @param obj
	 */
	public void update(T obj)
	{
		this.getHibernateTemplate().update(obj);
	}

	/**
	 * 删除一个对象
	 * 
	 * @author zhangym
	 * @create 2008-10-16 下午05:00:21
	 * @since
	 * @param obj
	 */
	public void delete(T obj)
	{
		this.getHibernateTemplate().delete(obj);
	}

	/**
	 * 根据主键,获得对象
	 * 
	 * @author zhangym
	 * @create 2008-10-16 下午05:45:33
	 * @since
	 * @param key
	 * @return
	 */
	public T getByKey(Serializable key)
	{
		return getHibernateTemplate().get(getEntryClass(), key);
	}

	/**
	 * 根据实例,获得对象集
	 * 
	 * @author zhangym
	 * @create 2008-10-16 下午05:46:07
	 * @since
	 * @param obj
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<T> findByExample(T obj)
	{
		return getHibernateTemplate().findByExample(obj);
	}

	/**
	 * 加载所有对象
	 * 
	 * @author zhangym
	 * @create 2008-10-16 下午05:46:47
	 * @since
	 * @return
	 */
	public List<T> loadAll()
	{
		return getHibernateTemplate().loadAll(getEntryClass());
	}

	/**
	 * 查找数据
	 * 
	 * @param hql
	 */
	@SuppressWarnings("unchecked")
	public <X> List<X> search(String hql)
	{
		return this.getHibernateTemplate().find(hql);
	}

	/**
	 * 
	 * 分页查询
	 *
	 * @param page
	 * @param hql
	 * @param values
	 * @return
	 *
	 */
	@SuppressWarnings("unchecked")
	public Page<T> queryPage(Page<T> page, String hql, Object... values)
	{
		Assert.notNull(page, "page不能为空");

		Query q = createQuery(hql, values);

		if (page.isAutoCount())
		{
			int totalCount = countHqlResult(hql, values);
			page.setTotalCount(totalCount);
		}

		setPageParameter(q, page);
		List<T> result = q.list();
		page.setResultList(result);
		return page;
	}

	/**
	 * 
	 * 分页查询
	 *
	 * @param page
	 * @param hql
	 * @param values
	 * @return
	 *
	 */
	@SuppressWarnings("unchecked")
	public Page<T> queryPage(Page<T> page, String hql,
			Map<String, Object> values)
	{
		Assert.notNull(page, "page不能为空");

		Query q = createQuery(hql, values);

		if (page.isAutoCount())
		{
			int totalCount = countHqlResult(hql, values);
			page.setTotalCount(totalCount);
		}

		setPageParameter(q, page);
		List<T> result = q.list();
		page.setResultList(result);

		return page;
	}

	/**
	 * 
	 * Description : 设置分页参数到Query对象,辅助函数
	 * 
	 * @param q
	 * @param page
	 * @return
	 * 
	 */
	@SuppressWarnings("static-access")
	private Query setPageParameter(final Query q, final Page<T> page)
	{
		// 如果每页显示的记录数 为-1，查询所有记录 ，不做分页
		if (page.getPageSize() != page.ALL_SIZE)
		{
			q.setFirstResult(page.getBeginCount());
			q.setMaxResults(page.getPageSize());
		}
		return q;
	}

	public Query createQuery(String queryString, Map<String, Object> values)
	{
		Assert.hasText(queryString, "queryString不能为空");
		Query query = getSession().createQuery(queryString);
		query.setCacheable(true);
		if (values != null)
		{
			query.setProperties(values);
		}

		return query;
	}

	public Query createQuery(String queryString, Object... values)
	{
		Assert.hasText(queryString, "queryString不能为空");
		Query query = getSession().createQuery(queryString);
		query.setCacheable(true);
		if (values != null)
		{
			for (int i = 0; i < values.length; i++)
			{
//				if (values[i] != null
//						&& StringUtils.isNotEmpty(values[i].toString()))
					query.setParameter(i, values[i]);
			}
		}

		return query;
	}

	public int countHqlResult(String hql, Object... values)
	{
		String fromHql = hql;

		// select子句与order by子句会影响count查询,进行简单的排除.
		fromHql = "from " + StringUtils.substringAfter(fromHql, "from");
		fromHql = StringUtils.substringBefore(fromHql, "order by");

		String selectHql = "*";
		// 如果含有 distinct 描述符，进行简单处理
		if (StringUtils.indexOf(hql, "distinct") != -1)
		{
			selectHql = StringUtils.substringBetween(hql, "select", "from")
					.trim();
		}
		String countHql = "select count(" + selectHql + ") " + fromHql;

		try
		{
			Long count = findUnique(countHql, values);
			return count.intValue();
		} catch (Exception e)
		{
			throw new RuntimeException("hql can't be auto count, hql is:"
					+ countHql, e);
		}
	}

	public int countHqlResult(String hql, Map<String, Object> values)
	{
		String fromHql = hql;
		// select子句与order by子句会影响count查询,进行简单的排除.
		fromHql = "from " + StringUtils.substringAfter(fromHql, "from");
		fromHql = StringUtils.substringBefore(fromHql, "order by");

		String countHql = "select count(*) " + fromHql;

		try
		{
			Long count = findUnique(countHql, values);
			return count.intValue();
		} catch (Exception e)
		{
			throw new RuntimeException("hql can't be auto count, hql is:"
					+ countHql, e);
		}
	}

	@SuppressWarnings("unchecked")
	public <X> X findUnique(String hql, Object... values)
	{
		return (X) createQuery(hql, values).uniqueResult();
	}

	@SuppressWarnings("unchecked")
	public <X> X findUnique(String hql, Map<String, Object> values)
	{
		return (X) createQuery(hql, values).uniqueResult();
	}
}